#include <iostream>
#include <memory>
#include <vector>

// 糟糕的设计
class ImageProcessor
{
public:
    // 问题1：参数顺序容易混淆
    // 问题2：缺乏参数范围检查
    // 问题3：返回值使用容易出错
    bool processImage(int width, int height, int format,
                      const char *data, int quality);
};

// 改进后的设计
// 1. 使用强类型枚举防止格式出错
enum class Format
{
    PNG,
    JPEG,
    WEBP
};
// 2.使用专门的类型封装参数
class Dimension
{
public:
    explicit Dimension(uint32_t width, uint32_t height)
    {
        if (width == 0 || height == 0)
            throw std::invalid_argument("Invalid dimension");

        if (width > MAX_WIDTH || height > MAX_HEIGHT)
            throw std::invalid_argument("Dimension too large");

        width_ = width;
        height_ = height;
    }
    uint32_t width() const { return width_; }
    uint32_t height() const { return height_; }

private:
    // constexpr 让变量/汉书在编译时就被计算好，直接嵌入到代码中
    static constexpr uint32_t MAX_WIDTH = 16384;
    static constexpr uint32_t MAX_HEIGHT = 16384;
    uint32_t width_;
    uint32_t height_;
};

// 3.使用Builder模式简化配置
class ProcessingOptions
{
public:
    // 提供合理默认值
    ProcessingOptions() : quality_(80), format_(Format::PNG) {}
    static ProcessingOptions createDefault()
    {
        return ProcessingOptions();
    }

    /**
     * @details 返回自身的引用，高效；如果返回的是值，每次调用都会创建新的对象
     */
    ProcessingOptions &setQuality(int q)
    {
        if (q < 0 || q > 100)
            throw std::invalid_argument("Quality must be 0-100");

        quality_ = q;
        return *this; // 返回当前对象的引用
    }

    ProcessingOptions &setFormat(Format f)
    {
        format_ = f;
        return *this;
    }

    int quality() const { return quality_; }
    Format format() const { return format_; }

private:
    int quality_;
    Format format_;
};

class Image
{
public:
    // 5.使用智能指针管理资源
    using ImagePtr = std::shared_ptr<Image>;

    // 6.工厂方法确保对象创建的正确性
    static ImagePtr create(const Dimension &dim, const std::vector<uint8_t> &data)
    {
        if (data.size() != dim.width() * dim.height() * 4)
            throw std::invalid_argument("Data size mismatch");
        return std::make_shared<Image>(dim, data);
    }

    // 7.处理结果使用Result类型封装
    struct ProcessResult
    {
        bool success;
        std::string error_message;
        std::vector<uint8_t> processed_data;
    };

    ProcessResult process(const ProcessingOptions &options) const
    {
        ProcessResult result;
        try
        {
            // 处理图像
            result.success = true;
        }
        catch (const std::exception &e)
        {
            result.success = false;
            result.error_message = e.what();
        }
        return result;
    }

private:
    Image(const Dimension &dim, const std::vector<uint8_t> &data) : dimension_(dim), data_(data) {}

    Dimension dimension_;
    std::vector<uint8_t> data_;
};

int main()
{
    try
    {
        // 创建图像尺寸
        Dimension dim(1920, 1080);

        // 准备图像数据
        std::vector<uint8_t> raw_data(1920 * 1080 * 4);

        // 创建图像对象
        auto img = Image::create(dim, raw_data);

        // 配置处理选项
        auto options = ProcessingOptions::createDefault().setQuality(90).setFormat(Format::JPEG);

        // 处理图像
        auto result = img->process(options);

        // 处理结果
        if (result.success)
        {
        }
        else
        {
            std::cerr << "error: " << result.error_message << std::endl;
        }
    }
    catch (const std::exception &e)
    {
        std::cerr << e.what() << '\n';
    }
}